<template>
    <Modal
        title="预约安装"
        width="600"
        :value="show"
        :mask-closable="false"
        @on-visible-change="setVisibility">

        <Alert>
            下单时，如有疑问，请拨打客服热线: 4000-101-110
        </Alert>

        <Alert type="warning" v-show="isWrongTime">
            {{form.subscribe.expected_time | date('MM月DD日')}}的工单已过派单时间，请拨打4000-101-110，告知客服要追加工单
        </Alert>

        <Form
            style="padding-right:20px"
            :model="form"
            :rules="rules"
            ref="createAppointment"
            :label-width="130"
            :show-message="false"
            label-position='right'>

            <Row class="margin-top-20">
                <i-col span="12">
                    <FormItem label="联系人"  prop="subscribe.name" >
                        <i-input v-model="form.subscribe.name"></i-input>
                    </FormItem>
                </i-col>
                <i-col span="12">
                    <FormItem label="联系人电话" prop="subscribe.phone">
                        <Input v-model="form.subscribe.phone"></Input>
                    </FormItem>
                </i-col>
            </Row>

            <!-- 垃圾iview -->
            <FormItem label="公寓地址" prop="home_id">
                <i-select
                    v-if="show && !fixedHome"
                    filterable
                    remote
                    :remote-method="searchHomes"
                    placeholder="请输入公寓地址"
                    @on-change="getRoom"
                    :loading="loadingHomes">
                    <i-option
                        v-for="(option, index) in homes"
                        :key="index"
                        :value="option.id">
                        {{concatLocation(option) + '(' + option.home_name + ')'}}
                    </i-option>
                </i-select>
                <!-- 固定地址时候 homes只有一个数组 -->
                <i-input
                    v-else
                    :disabled="fixedHome"
                    :value="homes.length ? concatLocation(homes[0]) : ''"
                ></i-input>
            </FormItem>

            <FormItem label="设备类型" prop="service_target">
                <Select
                    v-model="form.service_target"
                    @on-change="handleDeviceTypeChange"
                    placeholder="请选择设备类型">
                    <Option
                        v-for="(device,index) in deviceType"
                        :key="index"
                        :value="device.id">
                        {{device.name}}
                    </Option>
                </Select>
            </FormItem>

            <transition name="ease">
                <FormItem label="下单设备" v-if="shouldShowDeviceModel" class="ivu-form-item-required">
                    <div style="margin-bottom: -10px">
                        <Row :gutter="10" type="flex" class="margin-bottom-10" v-for="(device, key) in form.product_device_list" :key="key">
                            <i-col span="10">
                                <FormItem
                                    :prop="'product_device_list.' + key + '.device_product_id'"
                                    :rules="{required: true}">
                                    <Select v-model="device.device_product_id" @on-change="(val) => handleModelChange(val, key)">
                                        <Option
                                            v-for="model in deviceModel"
                                            :key="model.id"
                                            :value="model.id"
                                            :disabled="selectedProducts.includes(model.id)">{{model.name}}</Option>
                                    </Select>
                                </FormItem>
                            </i-col>
                            <i-col span="10">
                                <FormItem :prop="'product_device_list.' + key + '.estimate_quantity'" :rules="{required: true}">
                                    <Tooltip
                                        class="full-tool"
                                        :content="'最大数量' + (device.maxCount !== undefined ? device.maxCount : '总数小于房间数量')">
                                        <InputNumber
                                            v-model="device.estimate_quantity"
                                            class="width-100"
                                            :min="0"
                                            :max="device.maxCount || 1000"></InputNumber>
                                    </Tooltip>
                                </FormItem>
                            </i-col>
                            <i-col span="4">
                                <i-button icon="plus" v-if="key === 0" @click="handleAddDevice"></i-button>
                                <i-button icon="minus" v-else @click="handleDeleteDevice(key)"></i-button>
                            </i-col>
                        </Row>
                    </div>
                </FormItem>
            </transition>

            <!-- 使用iview animation -->
            <transition name="ease">
                <FormItem label="房间号" prop="faults" v-show="rooms.length && form.service_target">
                    <!-- 集中式房间选择器 -->
                    <room-selector
                        ref="roomSelector"
                        v-model="form.faults"
                        :rooms="rooms"
                        :device-type="form.service_target"
                        v-if="isConcentrateHome"></room-selector>
                    <!-- 分散式房间选择器 -->
                    <Select
                        v-else
                        multiple
                        v-model="form.faults"
                        placeholder="请选择房间 (可多选)"
                        @on-change="handleSelecAll">
                        <Option value="all">{{selectAll ? '取消全选' : '全选'}}</Option>
                        <Option
                            v-for="(item, index) in rooms"
                            :value="item.id"
                            :disabled="haveDevice(item, form.service_target).fill"
                            :key="index">
                            {{item.room_name + haveDevice(item, form.service_target).message}}
                        </Option>
                    </Select>
                </FormItem>
            </transition>

            <FormItem label="期待上门时间" prop="subscribe.expected_time">
                <Row type="flex" :gutter="10">
                    <i-col span="12">
                        <DatePicker
                            style="width: 100%"
                            v-model="form.subscribe.expected_time"
                            type="datetime"
                            format="yyyy-MM-dd"
                            placeholder="请选择时间"
                            :options="options"></DatePicker>
                    </i-col>
                    <i-col span="12">
                        <Select v-model="form.subscribe.expected_period">
                            <Option :value="1">全天</Option>
                            <Option :value="2" :disabled="isNotMoring">上午</Option>
                            <Option :value="3">下午</Option>
                        </Select>
                    </i-col>
                </Row>
            </FormItem>
            <FormItem label="时段" style="display:none" prop="subscribe.expected_period"></FormItem>

            <FormItem label="备注" prop="subscribe.note" style="margin-bottom:0">
                <i-input
                    v-model="form.subscribe.note"
                    type="textarea"
                    :autosize="{minRows: 3, maxRows: 4}"
                    placeholder="请输入备注"></i-input>
            </FormItem>

        </Form>

        <div slot="footer">
            <Button type="text" @click="setVisibility(false)">取消</Button>
            <Button type="primary" :loading="loading" @click="handleSubmit">保存</Button>
        </div>
    </Modal>
</template>

<script>
import dayjs from 'dayjs'
import validate from '@/libs/validate'
import dataCenter from '@/libs/dataCenter'
import { http, api } from '@/libs/http'
import util from '@/libs/util'
import roomSelector from '../components/room-selector.vue'

export default {
  name: 'create-appointment',
  components: {
    roomSelector
  },
  props: {
    show: Boolean,
    ticket: Object,
    home: Object,
    fixedHome: Boolean // true为非编辑模式
  },
  computed: {
    /**
         * 商户类型为先款后货，且下单商品为【电表、门锁和无网关门锁】，则必须填写下单设备类型 和 设备数量
         * 下单商品为【冷水表或热水表】，则不显示填写下单设备类型 和 设备数量
         */
    shouldShowDeviceModel () {
      return this.form.service_target && [2, 3, 4].includes(this.form.service_target) && this.isPayFirst
    },
    selectedProducts () {
      return this.form.product_device_list.map(item => item.device_product_id)
    },
    isNotMoring () {
      const { todayNoon, midnight } = this
      const now = +new Date()
      const appointmentTime = dayjs(this.form.subscribe.expected_time).valueOf()
      if (now > todayNoon && midnight >= appointmentTime) {
        if (this.form.subscribe.expected_period === 2) {
          this.form.subscribe.expected_period = 1
        }
        return true
      }
      return false
    },
    isWrongTime () {
      const expected_time = dayjs(this.form.subscribe.expected_time).valueOf()
      // 预约时间今天18点前, 只能预约在明天, 选在今天则提出警告
      const todayTicket = this.currentHour < 18 && expected_time < this.midnight
      // 预约时间今天18点之后, 只能预约在后天, 选在今天或明天则提出警告
      const tomorrowTicket =
                this.currentHour >= 18 &&
                expected_time <
                    dayjs(this.midnight)
                      .add(1, 'd')
                      .valueOf()
      return todayTicket || tomorrowTicket
    }
  },
  created () {
    this.fetchClientInfo()
  },
  data () {
    const currentHour = dayjs().hour()
    const expected_time = currentHour < 18 ? dayjs().add(1, 'd') : dayjs().add(2, 'd')
    return {
      isPayFirst: false,
      todayNoon: dayjs()
        .hour(12)
        .minute(0)
        .second(0)
        .valueOf(),
      midnight: dayjs()
        .hour(23)
        .minute(59)
        .second(59)
        .valueOf(),
      currentHour: dayjs().hour(),
      isConcentrateHome: false, // 是否是集中式房源
      loading: false,
      options: {
        disabledDate (date) {
          return date && date.valueOf() < Date.now() - 86400000
        }
      },
      selectAll: false, // 全选
      loadingHomes: false,
      homes: [],
      rooms: [],
      deviceModel: [], // 当前设备类型下的设备型号
      deviceMap: {}, // 当前设备类型下的设备型号的 {id: name} 键值对
      devicesModel: {
        device_product_id: '',
        estimate_quantity: 0
      },
      form: {
        home_id: '',
        service_target: '', // 与设备类型相同
        subscribe: {
          name: '',
          phone: '',
          note: '',
          expected_time: expected_time.format('YYYY-MM-DD'),
          expected_period: 1
        },
        product_device_list: [
          {
            device_product_id: '',
            estimate_quantity: 0
          }
        ],
        faults: [] // 房间信息
      },
      rules: {
        home_id: { required: true },
        service_target: { required: true },
        faults: { required: true, type: 'array' },
        'subscribe.name': { required: true },
        'subscribe.phone': [{ required: true, message: '请填写手机号码' }, { validator: validate.validPhone }],
        'subscribe.expected_time': { required: true },
        'subscribe.expected_period': { required: true }
      },
      deviceType: [
        { id: 2, name: '门锁' },
        { id: 3, name: '电表' },
        { id: 4, name: '无网关门锁' },
        { id: 6, name: '冷水表' },
        { id: 7, name: '热水表' }
      ]
    }
  },
  watch: {
    show (n) {
      if (n) {
        const { userName, telephone } = this.$store.state.user
        this.form.subscribe.name = userName
        this.form.subscribe.phone = telephone
        if (this.ticket) {
          this.initData()
        }
      } else {
        this.$refs.createAppointment.resetFields()
        this.rooms = []
        this.homes = []
        this.selectAll = false
        this.$emit('update:ticket', null)
      }
    }
  },
  methods: {
    concatLocation: util.concatLocation,
    /**
         * 将ticket字段copy到this.form中,
         * form中没有的字段另外配置
         */
    copyTicket () {
      for (let i in this.form) {
        if (i === 'home_id') {
          this.form.home_id = this.ticket.home_id
        } else if (i === 'faults') {
          this.form[i] = []
        } else if (i === 'product_device_list') {
          this.form.product_device_list = [{ ...this.devicesModel }]
        }
      }
    },
    setVisibility (val) {
      this.$emit('update:show', val)
    },
    async fetchClientInfo (clientId) {
      const info = await http.req(api.client_finance_info, null, null)
      this.isPayFirst = info && info.payment_type === 3
    },
    /**
         * 预约工单的设备类型独立于其他地方的设备类型,
         * 其中类型4无网关门锁即为门锁, 通过门锁上限判断
         */
    haveDevice (room, type) {
      if (type === 4) type = 2
      let result = { message: '', fill: false }
      if (Object.keys(room.devicesType).includes(type + '')) {
        result.message = ' [已有该设备]'
      }
      const data = {
        2: 1, // 门锁上限1个
        3: 4, // 电表上限4个
        4: 1, // 无网关门锁1个
        6: 2, // 水表上限2个
        7: 2 // 水表上限2个
      }
      if (data[type] <= room.devicesType[type]) {
        result.message = ' [设备达到上限]'
        result.fill = true
      }
      return result
    },
    handleSelecAll (value) {
      if (value.includes('all')) {
        this.selectAll = !this.selectAll
        if (this.selectAll) {
          const result = this.rooms
            .filter(room => {
              return !this.haveDevice(room, this.form.service_target).fill
            })
            .map(room => room.id)
          this.form.faults = [...result]
        } else {
          this.form.faults = []
        }
      }
    },
    handleDeviceTypeChange (type) {
      if (!this.fixedHome) {
        this.selectAll = false
        this.form.faults = []
        this.$refs.roomSelector && this.$refs.roomSelector.$setModel(this.form.faults)
      }
      if (type) {
        this.getDeviceModel(type)
        this.handleResetDevice()
      }
    },
    async getDeviceModel (deviceType) {
      this.deviceModel = await dataCenter.getDeviceModel(deviceType)
      const deviceMap = {}
      this.deviceModel.forEach(item => {
        deviceMap[item.id] = item.name
      })
      this.deviceMap = deviceMap
    },
    /**
         * 创建快捷工单时, 根据ticket补全this.form信息
         */
    async initData () {
      // const home = await this.getHome(this.ticket.home_id)
      this.homes = [
        {
          ...this.ticket.home_info,
          id: this.ticket.home_id
        }
      ]
      this.copyTicket()
      // ticket_devices没有id, 如果有bug, 可能是room_name的重复了
      await this.getRoom(this.ticket.home_id)
      this.$nextTick(() => {
        const roomNames = this.ticket.ticket_devices.map(room => room.room_name) || []
        this.form.faults = this.rooms.filter(room => roomNames.includes(room.room_name)).map(room => room.id)
        this.$refs.roomSelector && this.$refs.roomSelector.$setModel(this.form.faults)
      })
    },
    getHome (id) {
      if (!id) return Promise.resolve()
      return new Promise(resolve => {
        http.request(this, api.home_info, [id], null, res => {
          resolve(res)
        })
      })
    },
    searchHomes (query) {
      if (this.fixedHome) return
      if (this.form.faults.length) {
        this.selectAll = false
        this.form.faults = []
      }
      // 搜索房源
      if (query) {
        let params = {
          keyword: query
        }
        this.loadingHomes = true
        http.request(this, api.home_list, null, params, res => {
          if (res) {
            this.homes = res.homes
          }
          this.loadingHomes = false
        })
      }
    },
    /**
         * 快捷工单, prop入home: {home_type}对象判断是否集中式房源
         * 否则通过查找ajax结果列表对比选中id找出选中房间
         * 如果是集中式房源则使用集中式房源的房间选择器
         * @return {Promise}
         */
    getRoom (id) {
      if (!id) return
      this.form.home_id = id
      const home = this.homes.find(home => home.id === +this.form.home_id)
      const homeType = this.home ? this.home.home_type : home.home_type
      this.isConcentrateHome = homeType === 2
      return new Promise(resolve => {
        http.request(this, api.room_list, [id], { with_device: 1 }, (res, err) => {
          if (!res || err) return
          this.rooms = this.genRoomsData(res)
          resolve()
        })
      })
    },
    /**
         * 简化room列表结构, 并为房间内设备类型计数,
         * 在判断房间设备有没达到上限时使用
         */
    genRoomsData (data) {
      return data.sort((a, b) => a.room_name.localeCompare(b.room_name)).map(value => {
        const devicesType = {}
        value.devices.forEach(device => {
          if (!devicesType[device.device_type]) devicesType[device.device_type] = 0
          devicesType[device.device_type] += 1
        })
        return {
          room_name: value.room_name,
          id: value.id,
          floor: value.floor,
          devicesType
        }
      })
    },
    /**
         * 检查数量0的设备型号
         */
    wrongProductCount () {
      let error = this.form.product_device_list.some(item => item.device_product_id && item.estimate_quantity === 0)
      if (error) this.$Message.error('下单设备数量请勿填写数量0')
      return error
    },
    /**
         * 判断设备型号是否需要限制
         */
    wrongDeviceCount () {
      if (!this.shouldShowDeviceModel) return Promise.resolve(false)
      let error = false
      const { service_target, product_device_list, faults } = this.form
      const roomsSum = faults.length
      if (service_target === 2 || service_target === 4) {
        const productSum = product_device_list.reduce((sum, next) => {
          /** 不计算网关和采集器 */
          return [6, 7, 20].includes(next.device_product_id) ? sum : sum + next.estimate_quantity
        }, 0)
        if (productSum > roomsSum) {
          error = '<p class="margin-bottom-10">门锁下单数大于房间数量，确定下单?</p><p>门锁，每间只能绑一把</p>'
        }
      } else if (service_target === 3) {
        let normalElemeterSum = 0
        let A4ElemeterSum = 0
        product_device_list.forEach(item => {
          /** 不计算网关和采集器 */
          if ([6, 7, 20].includes(item.device_product_id)) return
          if (this.deviceMap[item.device_product_id].includes('A4')) {
            A4ElemeterSum += item.estimate_quantity
          } else {
            normalElemeterSum += item.estimate_quantity
          }
        })
        if (normalElemeterSum + Math.ceil(A4ElemeterSum / 4) > roomsSum) {
          error = '<p class="margin-bottom-10">电表下单数大于房间数量，确定下单？</p><p>注：电表，除A4和A4P每间房间可以绑4个，其他类型电表每间房间只能绑1个</p>'
        }
      }
      return error ? new Promise(resolve => {
        this.$Modal.confirm({
          title: '异常提示',
          content: error,
          onOk: () => {
            resolve(false)
          },
          onCancel: () => {
            resolve(true)
          }
        })
      }) : Promise.resolve(false)
    },
    handleSubmit () {
      this.loading = true
      this.$refs.createAppointment.validate(async valid => {
        if (valid) {
          if (this.wrongProductCount()) {
            this.loading = false
            return
          }
          const stop = await this.wrongDeviceCount()
          if (stop) {
            this.loading = false
            return
          }
          this.create()
        } else {
          this.$Message.error('信息未填写完整')
          this.loading = false
        }
      })
    },
    generateRequestData () {
      const { product_device_list, service_target, subscribe, home_id, faults } = this.form

      const data = {
        home_id,
        service_target,
        subscribe: { ...subscribe },
        public_auth: true,
        faults: []
      }

      data.subscribe.expected_time = dayjs(data.subscribe.expected_time).valueOf()

      this.rooms.forEach(room => {
        if (faults.includes(room.id)) {
          data.faults.push({
            room_id: room.id,
            room_name: room.room_name
          })
        }
      })

      if (this.shouldShowDeviceModel) {
        data.product_device_list = product_device_list.map(item => ({
          device_product_id: item.device_product_id,
          estimate_quantity: item.estimate_quantity
        }))
      }

      return data
    },
    /**
         * 创建新工单
         * form.faults绑定的是room id,
         * 请求的faults转换成房间信息数组
         */
    create () {
      const data = this.generateRequestData()

      http.request(this, api.ticket_add, [1], data, (res, err) => {
        this.loading = false
        if (err || !res) return
        this.$Message.success('添加成功')
        this.$emit('refresh')
        this.setVisibility(false)
      })
    },
    /**
         * 型号改变时候检查库存
         * @param {{}} index form.product_device_list的item的index
         */
    async handleModelChange (type, index, notReset) {
      if (type === undefined || index === undefined) return
      const select = this.deviceModel.find(model => model.id === type)
      this.$set(this.form.product_device_list[index], 'maxCount', select.client_order_statistics[0].real_quantity)
      !notReset && this.$set(this.form.product_device_list[index], 'estimate_quantity', 0)
    },
    /** 添加下单设备 */
    handleAddDevice () {
      this.form.product_device_list.push({ ...this.devicesModel })
    },
    handleDeleteDevice (index) {
      this.form.product_device_list.splice(index, 1)
    },
    handleResetDevice () {
      this.form.product_device_list = [{ ...this.devicesModel }]
    }
  }
}
</script>